package org.chartsy.annotation.text; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.Stroke; import java.awt.event.MouseEvent; import java.awt.font.LineBreakMeasurer; import java.awt.font.TextAttribute; import java.awt.font.TextLayout; import java.awt.geom.Point2D; import java.text.AttributedCharacterIterator; import java.text.AttributedString; import java.util.ArrayList; import java.util.List; import org.chartsy.main.AnnotationPanel; import org.chartsy.main.ChartFrame; import org.chartsy.main.chart.Annotation; import org.chartsy.main.managers.AnnotationManager; import org.chartsy.main.utils.SerialVersion; import org.openide.DialogDisplayer; import org.openide.NotifyDescriptor; import org.openide.nodes.AbstractNode; /** * * @author Viorel */ public class TextAnnotation extends Annotation { private static final long serialVersionUID = SerialVersion.APPVERSION; private AnnotationProperties properties; public TextAnnotation() { super(); } public TextAnnotation(ChartFrame frame) { super(frame); actionSet.set(TOP); actionSet.set(TOP_LEFT); actionSet.set(TOP_RIGHT); actionSet.set(LEFT); actionSet.set(RIGHT); actionSet.set(BOTTOM); actionSet.set(BOTTOM_LEFT); actionSet.set(BOTTOM_RIGHT); properties = new AnnotationProperties(); } public @Override String getName() { return "Text"; } public Annotation newInstance(ChartFrame frame) { return new TextAnnotation(frame); } public boolean pointIntersects(double x, double y) { if (getActionPoint(x, y) != NONE) return true; double X1 = getXFromTime(getT1()), X2 = getXFromTime(getT2()); double Y1 = getYFromValue(getV1()), Y2 = getYFromValue(getV2()); java.awt.Rectangle r = new java.awt.Rectangle(); r.setFrameFromDiagonal(X1, Y1, X2, Y2); return r.contains(x, y); } public void paint(Graphics2D g) { // get g properties java.awt.Rectangle oldClip = g.getClipBounds(); Font oldFont = g.getFont(); Stroke oldStroke = g.getStroke(); String text = properties.getText(); Font textFont = properties.getFont(); Color textColor = properties.getTextColor(); Color fillColor = properties.getFillColor(); Color borderColor = properties.getColor(); BasicStroke borderStroke = (BasicStroke) properties.getStroke(); double border = borderStroke.getLineWidth(); double X1 = getXFromTime(getT1()), X2 = getXFromTime(getT2()); double Y1 = getYFromValue(getV1()), Y2 = getYFromValue(getV2()); // initialize shape java.awt.Rectangle rectangle = new java.awt.Rectangle(); rectangle.setFrameFromDiagonal(X1, Y1, X2, Y2); // paint rectangle fill if visible if (properties.getInsideVisibility()) { g.setColor(fillColor); g.fill(rectangle); } // paint rectangle border g.setColor(borderColor); g.setStroke(borderStroke); g.draw(rectangle); // paint string inside the rectangle if (text != null && text.length() > 0) { g.setColor(textColor); g.setStroke(oldStroke); g.setFont(textFont); AttributedString attributedString = new AttributedString(text); attributedString.addAttribute(TextAttribute.FONT, textFont); AttributedCharacterIterator iterator = attributedString.getIterator(); LineBreakMeasurer measurer = new LineBreakMeasurer(iterator, g.getFontRenderContext()); float width = (float) ((X2 - X1) - (2 * border)); float Y = (float)(Y1 + border); List<TextLayout> layouts = new ArrayList<TextLayout>(); List<Point2D> points = new ArrayList<Point2D>(); TextLayout textLayout = null; while (measurer.getPosition() < iterator.getEndIndex()) { textLayout = measurer.nextLayout(width); Y += (textLayout.getAscent()); points.add(new Point2D.Double(X1 + borderStroke.getLineWidth(), Y)); layouts.add(textLayout); Y += textLayout.getDescent() + textLayout.getLeading(); } java.awt.Rectangle newClip = new java.awt.Rectangle(); newClip.setFrameFromDiagonal(X1 + border, Y1 + border, X2 - border, Y2 - border); g.setClip(newClip); for (int i = 0; i < layouts.size(); i++) { layouts.get(i).draw(g, (float)points.get(i).getX(), (float)points.get(i).getY()); } } // restore g properties g.setStroke(oldStroke); g.setFont(oldFont); g.setClip(oldClip); // paint action points if (isSelected()) paintActionPoints(g); } public @Override void mouseReleased(MouseEvent e) { if (isNew()) { NotifyDescriptor.InputLine notifyDescriptor = new NotifyDescriptor.InputLine( "Text:", "Type text for annotation", NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.PLAIN_MESSAGE); Object retval = DialogDisplayer.getDefault().notify(notifyDescriptor); if (retval.equals(NotifyDescriptor.OK_OPTION)) { String text = notifyDescriptor.getInputText(); if (text == null) text = ""; properties.setText(text); } } Annotation current = getAnnotationPanel().getCurrent(); if (current != null && current.isNew()) current.setNew(false); AnnotationManager.getDefault().clearNewAnnotation(); getAnnotationPanel().setState(AnnotationPanel.NONE); getAnnotationPanel().repaint(); } public AbstractNode getNode() { return new AnnotationNode(properties); } }